package com.fenrirtec.aepp.common.service.impl;

import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fenrirtec.aepp.common.dao.UserDao;
import com.fenrirtec.aepp.common.dao.impl.UserDao_JDBCImpl;
import com.fenrirtec.aepp.common.dto.GroupDto;
import com.fenrirtec.aepp.common.dto.UserDto;
import com.fenrirtec.aepp.common.model.Group;
import com.fenrirtec.aepp.common.model.User;
import com.fenrirtec.aepp.common.model.UserGroup;
import com.fenrirtec.aepp.common.service.UserManageService;
import com.fenrirtec.core.database.DatabaseSessionManager;
import com.fenrirtec.core.exception.DatabaseException;
import com.fenrirtec.core.exception.UnexpectedException;
import com.fenrirtec.core.utils.BeanCopierUtils;
import com.fenrirtec.core.utils.DigestUtils;

public class UserManageServiceImpl implements UserManageService {

	private static final Logger logger = LoggerFactory.getLogger(UserManageServiceImpl.class);

	@Override
	public UserDto login(String loginName, String loginPassword) {
		if (logger.isInfoEnabled()) {
			logger.info("[LoginServiceImpl#login] start.");
		}
		
		DatabaseSessionManager sessionManager = DatabaseSessionManager.getInstance();
		sessionManager.open();
		Connection connection = sessionManager.getSession();

		User user = null;
		
		try {
			connection.setAutoCommit(false);
			UserDao userDao = new UserDao_JDBCImpl();
			user = userDao.find(loginName);
			connection.commit();
		} catch (DatabaseException e) {
			// expected
			if (logger.isErrorEnabled()) {
				logger.error("[LoginServiceImpl#login] database error occurred.", e);
			}
			try {
				connection.rollback();
			} catch (SQLException e1) {
			}
			throw e;
		} catch (Exception e) {
			// unexpected
			if (logger.isErrorEnabled()) {
				logger.error("[LoginServiceImpl#login] unexpected error occurred.", e);
			}
			try {
				connection.rollback();
			} catch (SQLException e1) {
			}
			throw new UnexpectedException("unexpected error.", e);
		} finally {
			if (logger.isInfoEnabled()) {
				logger.info("[LoginServiceImpl#login] finish.");
			}
			sessionManager.close();
		}

		UserDto userDto = null;
		try {
			if (user != null && DigestUtils.SHAHashing(loginPassword).equals(user.getLoginPassword())) {
				userDto = new UserDto();
				BeanCopierUtils.copyProperties(user, userDto);
			}
		} catch (NoSuchAlgorithmException e) {
			// unexpected
			if (logger.isErrorEnabled()) {
				logger.error("[LoginServiceImpl#login] unexpected error occurred.", e);
			}
			throw new UnexpectedException("unexpected error.", e);
		}
		return userDto;
	}

    @Override
    public List<UserDto> findAll() {
        if (logger.isInfoEnabled()) {
            logger.info("[LoginServiceImpl#findAll] start.");
        }
        
        DatabaseSessionManager sessionManager = DatabaseSessionManager.getInstance();
        sessionManager.open();
        Connection connection = sessionManager.getSession();

        List<User> userList = null;
        
        try {
            connection.setAutoCommit(false);
            UserDao userDao = new UserDao_JDBCImpl();
            userList = userDao.findAll();
            connection.commit();
        } catch (DatabaseException e) {
            // expected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#findAll] database error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw e;
        } catch (Exception e) {
            // unexpected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#findAll] unexpected error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw new UnexpectedException("unexpected error.", e);
        } finally {
            if (logger.isInfoEnabled()) {
                logger.info("[LoginServiceImpl#findAll] finish.");
            }
            sessionManager.close();
        }

        List<UserDto> userDtoList = null;
        if (userList != null && userList.size() > 0) {
            userDtoList = new ArrayList<UserDto>();
            for (User user : userList) {
                UserDto userDto = new UserDto();
                BeanCopierUtils.copyProperties(user, userDto);
                userDtoList.add(userDto);
            }
        }
        return userDtoList;
    }

    @Override
    public List<GroupDto> findAllGroup() {
        if (logger.isInfoEnabled()) {
            logger.info("[LoginServiceImpl#findAllGroup] start.");
        }
        
        DatabaseSessionManager sessionManager = DatabaseSessionManager.getInstance();
        sessionManager.open();
        Connection connection = sessionManager.getSession();

        List<Group> groupList = null;
        
        try {
            connection.setAutoCommit(false);
            UserDao userDao = new UserDao_JDBCImpl();
            groupList = userDao.findAllGroup();
            connection.commit();
        } catch (DatabaseException e) {
            // expected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#findAllGroup] database error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw e;
        } catch (Exception e) {
            // unexpected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#findAllGroup] unexpected error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw new UnexpectedException("unexpected error.", e);
        } finally {
            if (logger.isInfoEnabled()) {
                logger.info("[LoginServiceImpl#findAllGroup] finish.");
            }
            sessionManager.close();
        }

        List<GroupDto> groupDtoList = null;
        if (groupList != null && groupList.size() > 0) {
            groupDtoList = new ArrayList<GroupDto>();
            for (Group group : groupList) {
                GroupDto groupDto = new GroupDto();
                BeanCopierUtils.copyProperties(group, groupDto);
                groupDtoList.add(groupDto);
            }
        }
        return groupDtoList;
    }

    @Override
    public List<UserDto> find(String keyword, String[] groups) {
        if (logger.isInfoEnabled()) {
            logger.info("[LoginServiceImpl#find] start.");
        }
        
        DatabaseSessionManager sessionManager = DatabaseSessionManager.getInstance();
        sessionManager.open();
        Connection connection = sessionManager.getSession();

        List<User> userList = null;
        
        try {
            connection.setAutoCommit(false);
            UserDao userDao = new UserDao_JDBCImpl();
            userList = userDao.find(keyword, groups);
            connection.commit();
        } catch (DatabaseException e) {
            // expected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#find] database error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw e;
        } catch (Exception e) {
            // unexpected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#find] unexpected error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw new UnexpectedException("unexpected error.", e);
        } finally {
            if (logger.isInfoEnabled()) {
                logger.info("[LoginServiceImpl#find] finish.");
            }
            sessionManager.close();
        }

        List<UserDto> userDtoList = null;
        if (userList != null && userList.size() > 0) {
            userDtoList = new ArrayList<UserDto>();
            for (User user : userList) {
                UserDto userDto = new UserDto();
                BeanCopierUtils.copyProperties(user, userDto);
                userDtoList.add(userDto);
            }
        }
        return userDtoList;
    }

    @Override
    public List<GroupDto> findGroup(String keyword) {
        if (logger.isInfoEnabled()) {
            logger.info("[LoginServiceImpl#findGroup] start.");
        }
        
        DatabaseSessionManager sessionManager = DatabaseSessionManager.getInstance();
        sessionManager.open();
        Connection connection = sessionManager.getSession();

        List<Group> groupList = null;
        
        try {
            connection.setAutoCommit(false);
            UserDao userDao = new UserDao_JDBCImpl();
            groupList = userDao.findGroup(keyword);
            connection.commit();
        } catch (DatabaseException e) {
            // expected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#findGroup] database error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw e;
        } catch (Exception e) {
            // unexpected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#findGroup] unexpected error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw new UnexpectedException("unexpected error.", e);
        } finally {
            if (logger.isInfoEnabled()) {
                logger.info("[LoginServiceImpl#findGroup] finish.");
            }
            sessionManager.close();
        }

        List<GroupDto> groupDtoList = null;
        if (groupList != null && groupList.size() > 0) {
            groupDtoList = new ArrayList<GroupDto>();
            for (Group group : groupList) {
                GroupDto groupDto = new GroupDto();
                BeanCopierUtils.copyProperties(group, groupDto);
                groupDtoList.add(groupDto);
            }
        }
        return groupDtoList;
    }

    @Override
    public UserDto findByLoginName(String loginName) {
        if (logger.isInfoEnabled()) {
            logger.info("[LoginServiceImpl#findByLoginName] start.");
        }
        
        DatabaseSessionManager sessionManager = DatabaseSessionManager.getInstance();
        sessionManager.open();
        Connection connection = sessionManager.getSession();

        User user = null;
        
        try {
            connection.setAutoCommit(false);
            UserDao userDao = new UserDao_JDBCImpl();
            user = userDao.find(loginName);
            connection.commit();
        } catch (DatabaseException e) {
            // expected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#findByLoginName] database error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw e;
        } catch (Exception e) {
            // unexpected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#findByLoginName] unexpected error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw new UnexpectedException("unexpected error.", e);
        } finally {
            if (logger.isInfoEnabled()) {
                logger.info("[LoginServiceImpl#findByLoginName] finish.");
            }
            sessionManager.close();
        }

        UserDto userDto = null;
        if (user != null) {
            userDto = new UserDto();
            BeanCopierUtils.copyProperties(user, userDto);
        }
        return userDto;
    }

    @Override
    public Boolean insert(UserDto userDto) {
        if (logger.isInfoEnabled()) {
            logger.info("[LoginServiceImpl#insert] start.");
        }
        
        DatabaseSessionManager sessionManager = DatabaseSessionManager.getInstance();
        sessionManager.open();
        Connection connection = sessionManager.getSession();

        Boolean result = false;
        
        try {
            connection.setAutoCommit(false);
            UserDao userDao = new UserDao_JDBCImpl();
            User user = new User();
            BeanCopierUtils.copyProperties(userDto, user);
            result = userDao.insert(user);
            
            if (result) {
                String groups = user.getUserGroup();
                if (StringUtils.isNotEmpty(groups)) {
                    for (String group : groups.split(",")) {
                        UserGroup userGroup = new UserGroup();
                        userGroup.setLoginName(user.getLoginName());
                        userGroup.setGroupName(group);
                        userGroup.setCreateUser(user.getCreateUser());
                        result = userDao.insert(userGroup);
                        if (!result) {
                            connection.rollback();
                            break;
                        }
                    }
                }
            } else {
                connection.rollback();
            }
            
            connection.commit();
        } catch (DatabaseException e) {
            // expected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#insert] database error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw e;
        } catch (Exception e) {
            // unexpected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#insert] unexpected error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw new UnexpectedException("unexpected error.", e);
        } finally {
            if (logger.isInfoEnabled()) {
                logger.info("[LoginServiceImpl#insert] finish.");
            }
            sessionManager.close();
        }

        return result;
    }

    @Override
    public Boolean update(UserDto userDto) {
        if (logger.isInfoEnabled()) {
            logger.info("[LoginServiceImpl#update] start.");
        }
        
        DatabaseSessionManager sessionManager = DatabaseSessionManager.getInstance();
        sessionManager.open();
        Connection connection = sessionManager.getSession();

        Boolean result = false;
        
        try {
            connection.setAutoCommit(false);
            UserDao userDao = new UserDao_JDBCImpl();
            User user = new User();
            BeanCopierUtils.copyProperties(userDto, user);
            result = userDao.update(user);
            
            if (result) {
                userDao.deleteUserGroup(user.getLoginName());
                String groups = user.getUserGroup();
                if (StringUtils.isNotEmpty(groups)) {
                    for (String group : groups.split(",")) {
                        UserGroup userGroup = new UserGroup();
                        userGroup.setLoginName(user.getLoginName());
                        userGroup.setGroupName(group);
                        userGroup.setCreateUser(user.getCreateUser());
                        result = userDao.insert(userGroup);
                        if (!result) {
                            connection.rollback();
                            break;
                        }
                    }
                }
            } else {
                connection.rollback();
            }
            
            connection.commit();
        } catch (DatabaseException e) {
            // expected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#update] database error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw e;
        } catch (Exception e) {
            // unexpected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#update] unexpected error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw new UnexpectedException("unexpected error.", e);
        } finally {
            if (logger.isInfoEnabled()) {
                logger.info("[LoginServiceImpl#update] finish.");
            }
            sessionManager.close();
        }

        return result;
    }

    @Override
    public Boolean delete(String loginName) {
        if (logger.isInfoEnabled()) {
            logger.info("[LoginServiceImpl#delete] start.");
        }
        
        DatabaseSessionManager sessionManager = DatabaseSessionManager.getInstance();
        sessionManager.open();
        Connection connection = sessionManager.getSession();

        Boolean result = false;
        
        try {
            connection.setAutoCommit(false);
            UserDao userDao = new UserDao_JDBCImpl();
            result = userDao.delete(loginName);
            if (result) {
                userDao.deleteUserGroup(loginName);
                connection.commit();
            } else {
                connection.rollback();
            }
            
        } catch (DatabaseException e) {
            // expected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#delete] database error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw e;
        } catch (Exception e) {
            // unexpected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#delete] unexpected error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw new UnexpectedException("unexpected error.", e);
        } finally {
            if (logger.isInfoEnabled()) {
                logger.info("[LoginServiceImpl#delete] finish.");
            }
            sessionManager.close();
        }

        return result;
    }

    @Override
    public GroupDto findByGroupName(String groupName) {
        if (logger.isInfoEnabled()) {
            logger.info("[LoginServiceImpl#findByGroupName] start.");
        }
        
        DatabaseSessionManager sessionManager = DatabaseSessionManager.getInstance();
        sessionManager.open();
        Connection connection = sessionManager.getSession();

        Group group = null;
        
        try {
            connection.setAutoCommit(false);
            UserDao userDao = new UserDao_JDBCImpl();
            group = userDao.findGroupByGroupName(groupName);
            connection.commit();
        } catch (DatabaseException e) {
            // expected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#findByGroupName] database error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw e;
        } catch (Exception e) {
            // unexpected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#findByGroupName] unexpected error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw new UnexpectedException("unexpected error.", e);
        } finally {
            if (logger.isInfoEnabled()) {
                logger.info("[LoginServiceImpl#findByGroupName] finish.");
            }
            sessionManager.close();
        }

        GroupDto groupDto = null;
        if (group != null) {
            groupDto = new GroupDto();
            BeanCopierUtils.copyProperties(group, groupDto);
        }
        return groupDto;
    }

    @Override
    public Boolean insert(GroupDto groupDto) {
        if (logger.isInfoEnabled()) {
            logger.info("[LoginServiceImpl#insert] start.");
        }
        
        DatabaseSessionManager sessionManager = DatabaseSessionManager.getInstance();
        sessionManager.open();
        Connection connection = sessionManager.getSession();

        Boolean result = false;
        
        try {
            connection.setAutoCommit(false);
            UserDao userDao = new UserDao_JDBCImpl();
            Group group = new Group();
            BeanCopierUtils.copyProperties(groupDto, group);
            result = userDao.insert(group);
            
            if (result) {
                connection.commit();
            } else {
                connection.rollback();
            }
            
        } catch (DatabaseException e) {
            // expected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#insert] database error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw e;
        } catch (Exception e) {
            // unexpected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#insert] unexpected error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw new UnexpectedException("unexpected error.", e);
        } finally {
            if (logger.isInfoEnabled()) {
                logger.info("[LoginServiceImpl#insert] finish.");
            }
            sessionManager.close();
        }

        return result;
    }

    @Override
    public Boolean update(GroupDto groupDto) {
        if (logger.isInfoEnabled()) {
            logger.info("[LoginServiceImpl#update] start.");
        }
        
        DatabaseSessionManager sessionManager = DatabaseSessionManager.getInstance();
        sessionManager.open();
        Connection connection = sessionManager.getSession();

        Boolean result = false;
        
        try {
            connection.setAutoCommit(false);
            UserDao userDao = new UserDao_JDBCImpl();
            Group group = new Group();
            BeanCopierUtils.copyProperties(groupDto, group);
            result = userDao.update(group);
            
            if (result) {
                connection.commit();
            } else {
                connection.rollback();
            }
            
        } catch (DatabaseException e) {
            // expected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#update] database error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw e;
        } catch (Exception e) {
            // unexpected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#update] unexpected error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw new UnexpectedException("unexpected error.", e);
        } finally {
            if (logger.isInfoEnabled()) {
                logger.info("[LoginServiceImpl#update] finish.");
            }
            sessionManager.close();
        }

        return result;
    }

    @Override
    public Boolean deleteGroup(String groupName) {
        if (logger.isInfoEnabled()) {
            logger.info("[LoginServiceImpl#delete] start.");
        }
        
        DatabaseSessionManager sessionManager = DatabaseSessionManager.getInstance();
        sessionManager.open();
        Connection connection = sessionManager.getSession();

        Boolean result = false;
        
        try {
            connection.setAutoCommit(false);
            UserDao userDao = new UserDao_JDBCImpl();
            result = userDao.deleteGroup(groupName);
            if (result) {
                userDao.deleteGroupUser(groupName);
                connection.commit();
            } else {
                connection.rollback();
            }
            
        } catch (DatabaseException e) {
            // expected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#delete] database error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw e;
        } catch (Exception e) {
            // unexpected
            if (logger.isErrorEnabled()) {
                logger.error("[LoginServiceImpl#delete] unexpected error occurred.", e);
            }
            try {
                connection.rollback();
            } catch (SQLException e1) {
            }
            throw new UnexpectedException("unexpected error.", e);
        } finally {
            if (logger.isInfoEnabled()) {
                logger.info("[LoginServiceImpl#delete] finish.");
            }
            sessionManager.close();
        }

        return result;
    }
}
